//
// Created by DengLibin on 2018/12/13 0013.
//

/**
 *生产者消费者
 */
#include<iostream>
#include<condition_variable>
#include<queue>
#include<thread>
std::condition_variable_any m_t;     //条件变量
std::mutex lock; //互斥锁
std::queue<int> q;//队列
int size = 5;//队列大小

int putSize = 0; //生产元素个数
int takeSize = 0;//消费元素个数

//生产元素
void put(int element)
{
    std::lock_guard<std::mutex> locker(lock);  //使用之前先加锁 std::lock_guard 在构造函数中进行加锁，析构函数中进行解锁。

    while (q.size() == size)//满了
    {
        std::cout << "满了" << std::endl;
        m_t.wait(lock);//将当前线程阻塞，注意：此时会释放锁
    }
    q.push(element);
    std::cout << "生产了一个元素:" << element << std::endl;
    putSize++;
    m_t.notify_all();//通知消费者消费
}
//消费元素
void take()
{
    std::lock_guard<std::mutex> locker(lock);  //使用之前先加锁
    while (q.size() == 0)//空了
    {
        std::cout << "空了" << std::endl;
        m_t.wait(lock);//将当前线程阻塞，注意：此时会释放锁
    }
    int& c = q.front();
    q.pop();
    std::cout << "消费了一个元素:" << c << std::endl;
    takeSize++;
    m_t.notify_all();//通知生产者生产
}
/*
detach方式，启动的线程自主在后台运行，当前的代码继续往下执行，不等待新线程结束
join方式，等待启动的线程完成，才会继续往下执行
*/
int main35(int argc, char* argv[])
{
    for (int i = 1; i <= 100; i++)
    {
        std::thread t1(put, i);
        t1.detach();
    }
    for (int i = 1; i <= 100; i++)
    {
        std::thread t2(take);
        t2.detach();
    }
    std::chrono::milliseconds dura(2000);
    std::this_thread::sleep_for(dura);
    std::cout << "生产元素个数:" << putSize << std::endl;
    std::cout << "消费元素个数:" << takeSize << std::endl;
    system("pause");
    return 0;
}